package com.inplaceedit.client.ui.note;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.editor.client.adapters.EditorSource;
import com.google.gwt.editor.client.adapters.ListEditor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.inplaceedit.client.ui.InPlaceEditPanel;
import com.inplaceedit.client.ui.SectionPanel;
import com.inplaceedit.shared.dto.NoteDto;

public class NoteListDisplayView extends Composite implements NoteListDisplay {

	private class NoteEditorSource extends EditorSource<NoteEditor> {
		private final Map<NoteEditor, Widget> widgetIndex;
		private final Map<NoteEditor, HandlerRegistration> editHandlerIndex;
		private final Map<NoteEditor, HandlerRegistration> deleteHandlerIndex;

		public NoteEditorSource() {
			widgetIndex = new HashMap<NoteEditor, Widget>();
			editHandlerIndex = new HashMap<NoteEditor, HandlerRegistration>();
			deleteHandlerIndex = new HashMap<NoteEditor, HandlerRegistration>();
		}

		@Override
		public NoteEditor create(final int index) {
			final NoteDisplayView display = new NoteDisplayView();
			final NoteEditorView editor = new NoteEditorView();
			final InPlaceEditPanel editPanel = new InPlaceEditPanel();
			final SectionPanel panel = new SectionPanel();
			editPanel.setDeleteCommandVisible(true);
			editPanel.setDisplayWidget(display);
			editPanel.setEditorWidget(editor);
			panel.getContentPanel().setWidget(editPanel);

			widgetIndex.put(display, panel);
			container.insert(panel, index);

			editHandlerIndex.put(display, editPanel.getEditCommand()
					.addClickHandler(new ClickHandler() {
						@Override
						public void onClick(final ClickEvent event) {
							if (handler != null) {
								final int index = container
										.getWidgetIndex(panel);
								if (index >= 0) {
									final NoteDto object = listEditor.getList()
											.get(index);
									handler.onEdit(object, editor,
											editPanel.asDialog());
								}
							}
						}
					}));

			deleteHandlerIndex.put(display, editPanel.getDeleteCommand()
					.addClickHandler(new ClickHandler() {
						@Override
						public void onClick(final ClickEvent event) {
							if (handler != null) {
								final int index = container
										.getWidgetIndex(panel);
								if (index >= 0) {
									final NoteDto object = listEditor.getList()
											.get(index);
									handler.onDelete(object);
								}
							}
						}
					}));

			return display;
		}

		@Override
		public void dispose(final NoteEditor display) {
			final HandlerRegistration editHandler = editHandlerIndex
					.get(display);
			if (editHandler != null) {
				editHandler.removeHandler();
			}
			editHandlerIndex.remove(display);

			final HandlerRegistration deleteHandler = deleteHandlerIndex
					.get(display);
			if (deleteHandler != null) {
				deleteHandler.removeHandler();
			}
			deleteHandlerIndex.remove(display);

			final Widget w = widgetIndex.get(display);
			if (w != null) {
				container.remove(w);
			}
			widgetIndex.remove(display);
		}

		@Override
		public void setIndex(final NoteEditor display, final int index) {
			final Widget w = widgetIndex.get(display);
			if (w != null) {
				container.insert(w, index);
			}
		}
	}

	private final FlowPanel container;
	private ListEditor<NoteDto, NoteEditor> listEditor;
	private Handler handler;

	public NoteListDisplayView() {
		container = new FlowPanel();
		initWidget(container);
	}

	@Override
	public ListEditor<NoteDto, NoteEditor> asEditor() {
		if (listEditor == null) {
			listEditor = ListEditor.of(new NoteEditorSource());
		}
		return listEditor;
	}

	@Override
	public void setHandler(final Handler handler) {
		this.handler = handler;
	}
}
